package com.slorgs.business.service.impl

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper
import com.baomidou.mybatisplus.extension.plugins.pagination.Page
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl
import com.slorgs.business.service.UserService
import com.slorgs.business.utils.*
import com.slorgs.infrastructure.dto.ResponseDTO
import com.slorgs.infrastructure.dto.UserDTO
import com.slorgs.infrastructure.mapper.UserMapper
import com.slorgs.infrastructure.model.User
import freemarker.template.Configuration
import org.slf4j.LoggerFactory
import org.springframework.data.redis.core.StringRedisTemplate
import org.springframework.http.HttpStatus
import org.springframework.stereotype.Service
import org.springframework.util.StringUtils
import java.io.StringWriter
import java.text.SimpleDateFormat
import java.util.*
import javax.annotation.Resource
import javax.mail.MessagingException


@Service
class UserServiceImpl : ServiceImpl<UserMapper, User>(), UserService {

    companion object {
        private val log = LoggerFactory.getLogger(UserServiceImpl::class.java)
    }

    @Resource
    var fmConfiguration: Configuration? = null

    @Resource
    var validateCodeUtils: ValidateCodeUtils? = null

    @Resource
    var userMapper: UserMapper? = null

    @Resource
    var stringRedisTemplate: StringRedisTemplate? = null

    @Resource
    var emailUtil: EmailUtil? = null
    override fun register(user: User?): ResponseDTO? {
        val responseDTO = ResponseDTO()
        if (StringUtils.isEmpty(user!!.idUser)) {
            if (!StringUtils.isEmpty(user.loginName) && !StringUtils.isEmpty(user.password)) {
                if (user.loginName.length < 6 || user.password.length < 9) {
                    responseDTO.code = HttpStatus.BAD_REQUEST.value()
                    responseDTO.message = "登录名或者密码长度太短"
                } else {
                    userMapper!!.insert(
                        User.builder()
                            .idUser(UUID.randomUUID().toString().replace("-".toRegex(), ""))
                            .loginName(user.loginName)
                            .createBy(user.loginName)
                            .role("client")
                            .createTime(Date())
                            .mail(user.mail)
                            .realName(user.realName)
                            .telephone(user.telephone)
                            .password(ShaUtil.getSha1(user.password))
                            .build()
                    )
                    responseDTO.code = HttpStatus.OK.value()
                    responseDTO.message = "注册成功"
                }
            } else {
                responseDTO.code = HttpStatus.NOT_ACCEPTABLE.value()
                responseDTO.message = "参数为空..."
            }
        } else {
        }
        return responseDTO
    }

    @Throws(MessagingException::class)
    private fun register(user: UserDTO) {
        val fullPwd = "1234567890ABCDEFGHIJKLMN,./@#*OPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
        val random = Random()
        val chars = CharArray(12)
        for (i in chars.indices) chars[i] = fullPwd[random.nextInt(68)]
        val password = String(chars)
        userMapper!!.insert(
            User.builder()
                .idUser(UUID.randomUUID().toString().replace("-".toRegex(), "")).loginName(user.mail)
                .createBy(user.mail).role("client").createTime(Date()).mail(user.mail)
                .realName(user.mail.substring(0, user.mail.lastIndexOf("@")))
                .telephone(user.telephone).password(ShaUtil.getSha1(password)).build()
        )
        emailUtil!!.sendMail(
            user.mail, "【深蓝数聚】注册成功",
            """
            Dear ${user.mail}:
            你的用户名为:${user.mail}；初始登陆密码为:[$password]请及时登陆后前往个人中心设置登陆密码。
            """.trimIndent(), false
        )
    }

    override fun login(user: UserDTO?): ResponseDTO? {
        val responseDTO = ResponseDTO()
        try {
            if (StringUtils.isEmpty(user!!.loginName) || StringUtils.isEmpty(
                    user.password
                ) || StringUtils.isEmpty(user.code) || StringUtils.isEmpty(
                    user.browsCode
                )
            ) {
                responseDTO.code = HttpStatus.BAD_REQUEST.value()
                responseDTO.message = "携带信息不完整"
                return responseDTO
            }
            if (!validateCodeUtils!!.checkVerify(user.code, user.browsCode, stringRedisTemplate!!)) {
                responseDTO.code = HttpStatus.BAD_REQUEST.value()
                responseDTO.message = "验证码错误"
                return responseDTO
            }
            val dbUser = userMapper!!.selectOne(QueryWrapper<User>().eq("loginName", user.loginName))
            if (dbUser == null) {
                responseDTO.code = HttpStatus.BAD_REQUEST.value()
                responseDTO.message = "账户或密码不存在"
                return responseDTO
            }
            if (!ShaUtil.verify(user.password, dbUser.password)) {
                responseDTO.code = HttpStatus.BAD_REQUEST.value()
                responseDTO.message = "账户或密码不存在"
                return responseDTO
            } else if ("admin" != dbUser.role) {
                responseDTO.code = HttpStatus.BAD_REQUEST.value()
                responseDTO.message = "你没有权限登录"
                return responseDTO
            }
            responseDTO.message = "登陆成功"
            responseDTO.code = HttpStatus.OK.value()
            responseDTO.data = TokenUtil.getToken(dbUser)
        } catch (e: java.lang.Exception) {
            log.error("登陆出现异常...", e)
            responseDTO.message = "登陆出现异常"
            responseDTO.code = HttpStatus.BAD_REQUEST.value()
        }
        return responseDTO
    }

    override fun portalLogin(user: UserDTO?, isPassword: Boolean): ResponseDTO? {
        val responseDTO = ResponseDTO()
        try {
            var dbUser: User?
            if (isPassword) {
                if (StringUtils.isEmpty(user!!.loginName) || StringUtils.isEmpty(
                        user.password
                    )
                ) {
                    responseDTO.code = HttpStatus.BAD_REQUEST.value()
                    responseDTO.message = "携带信息不完整"
                    return responseDTO
                }
                dbUser = userMapper!!.selectOne(
                    QueryWrapper<User>().eq("loginName", user.loginName).or().eq("mail", user.loginName)
                )
                if (dbUser == null) {
                    responseDTO.code = HttpStatus.BAD_REQUEST.value()
                    responseDTO.message = "账户或密码不存在"
                    return responseDTO
                } else {
                    if (!ShaUtil.verify(user.password, dbUser.password)) {
                        responseDTO.code = HttpStatus.BAD_REQUEST.value()
                        responseDTO.message = "账户或密码不正确"
                        return responseDTO
                    }
                }
            } else {
                if (StringUtils.isEmpty(user!!.mail) || StringUtils.isEmpty(
                        user.code
                    )
                ) {
                    responseDTO.code = HttpStatus.BAD_REQUEST.value()
                    responseDTO.message = "携带信息不完整"
                    return responseDTO
                }
                if (!stringRedisTemplate?.let { validateCodeUtils?.checkMailCode(user, it) }!!) {
                    responseDTO.message = "验证码错误"
                    responseDTO.code = HttpStatus.BAD_REQUEST.value()
                    return responseDTO
                }
                dbUser = userMapper!!.selectOne(QueryWrapper<User>().eq("mail", user.mail))
                if (dbUser == null) {
                    dbUser = User.builder().loginName(user.mail).realName(user.mail).build()
                    register(user)
                }
            }
            responseDTO.message = "登陆成功"
            responseDTO.code = HttpStatus.OK.value()
            responseDTO.data = TokenUtil.getToken(dbUser)
            if ("admin" == dbUser.role) {
                responseDTO.data = responseDTO.data as String? + "XDeep"
            }
        } catch (e: Exception) {
            log.error("门户用户登录出现异常...", e)
            responseDTO.message = "登陆出现异常"
            responseDTO.code = HttpStatus.BAD_REQUEST.value()
        }
        return responseDTO
    }

    override fun userList(user: User?, page: Page<*>?): ResponseDTO? {
        val responseDTO = ResponseDTO()
        responseDTO.data = userMapper?.selectList(Page<User>(page!!.current,page.size),user)
        return responseDTO
    }

    override fun serverAuthorize(onlyMark: String?): ResponseDTO? {
        val responseDTO = ResponseDTO()
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(onlyMark)) {
            try {
                if (org.apache.commons.lang3.StringUtils.isNotEmpty(
                        ThreadLocalUtil.getUser()?.role
                    ) && ThreadLocalUtil.getUser()?.role.equals("admin")
                ) {
                    val user = userMapper!!.selectOne(
                        QueryWrapper<User>().eq(
                            "loginName",
                            ThreadLocalUtil.getUser()?.loginName
                        )
                    )
                    val map: MutableMap<String, String> = HashMap()
                    map["name"] = user.realName
                    map["mark"] = onlyMark!!
                    map["time"] = SimpleDateFormat().format(Date())
                    val template = fmConfiguration!!.getTemplate("email_template.html")
                    val stringWriter = StringWriter()
                    template.process(map, stringWriter)
                    emailUtil!!.sendMail(user.mail, "身份认证", stringWriter.toString(), true)
                    WebsocketCertificationUtil.getInstance().add("auth$onlyMark", false)
                    responseDTO.message = "我们向你的邮箱发送了一条认证链接，请注意查收！"
                    return responseDTO
                }
            } catch (e: java.lang.Exception) {
                responseDTO.code = 500
                responseDTO.message = "授权异常"
            }
        }
        responseDTO.code = 500
        responseDTO.message = "请求有缺陷"
        return responseDTO
    }

    override fun commitAuth(onlyMark: String?): String? {
        if (org.apache.commons.lang3.StringUtils.isNotEmpty(onlyMark)) {
            try {
                val mark = "auth$onlyMark"
                if (WebsocketCertificationUtil.getInstance().getKey(mark)) {
                    WebsocketCertificationUtil.getInstance().add(mark, true)
                    return "认证完成"
                }
            } catch (e: java.lang.Exception) {
                log.error("认证异常", e)
            }
        }
        return "认证失败"
    }

    override fun checkAuth(onlyMark: String?): ResponseDTO? {
        val responseDTO = ResponseDTO()
        try {
            if (org.apache.commons.lang3.StringUtils.isNotEmpty(onlyMark)) {
                if (WebsocketCertificationUtil.getInstance().validate("auth$onlyMark")) {
                    responseDTO.message = "认证通过"
                    return responseDTO
                }
            }
            responseDTO.message = "认证未通过"
        } catch (e: java.lang.Exception) {
            log.error("检查认证出现异常...", e)
            responseDTO.message = "操作出现异常"
        }
        responseDTO.code = 500
        return responseDTO
    }
}